home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 4 / ETO Development Tools 4.iso / Tools - Objects / MacApp / MacApp 3.0a2 / Libraries / UDependencies.cp < prev    next >
Encoding:
Text File  |  1991-05-01  |  17.2 KB  |  549 lines  |  [TEXT/MPS ]

  1. // UDependencies.cp
  2. // Copyright © 1988-1991 by Apple Computer Inc.  All rights reserved.
  3.  
  4. #ifndef __UDEPENDENCIES__
  5. #include "UDependencies.h"
  6. #endif
  7.  
  8. #ifndef __PACKAGES__
  9. #include <Packages.h>
  10. #endif
  11. #ifndef __UITERATOR__
  12. #include <UIterator.h>
  13. #endif
  14.  
  15.  
  16. //--------------------------------------------------------------------------------------------------
  17.  
  18. TDependenciesByNotifier* gDependenciesByNotifier = NULL;
  19. TDependenciesByDependent* gDependenciesByDependent = NULL;
  20.  
  21. //--------------------------------------------------------------------------------------------------
  22. #pragma segment DepRes
  23.  
  24. pascal TDependenciesByNotifier* NewDependenciesByNotifier(void)
  25. {
  26.     TDependenciesByNotifier * dependencies = new TDependenciesByNotifier;
  27.  
  28.     dependencies->IDependencies();
  29.     return dependencies;
  30. }
  31.  
  32. //--------------------------------------------------------------------------------------------------
  33. #pragma segment DepRes
  34.  
  35. pascal TDependenciesByDependent* NewDependenciesByDependent(void)
  36. {
  37.     TDependenciesByDependent * dependencies = new TDependenciesByDependent;
  38.  
  39.     dependencies->IDependencies();
  40.     return dependencies;
  41. }
  42.  
  43. //--------------------------------------------------------------------------------------------------
  44. #pragma segment DepRes
  45.  
  46. pascal void AddDependentOf(TObject* notifier,
  47.                            TObject* dependent,
  48.                            DependencyLabels dependencyLabel)
  49. {
  50.     if (gDependenciesByNotifier == NULL)
  51.         gDependenciesByNotifier = NewDependenciesByNotifier();
  52.     if (gDependenciesByDependent == NULL)
  53.         gDependenciesByDependent = NewDependenciesByDependent();
  54.     gDependenciesByNotifier->AddDependency(notifier, dependent, dependencyLabel);
  55.     gDependenciesByDependent->AddDependency(notifier, dependent, dependencyLabel);
  56. }
  57.  
  58. //--------------------------------------------------------------------------------------------------
  59. #pragma segment DepRes
  60.  
  61. pascal void RemoveDependentOf(TObject* notifier,
  62.                               TObject* dependent,
  63.                               DependencyLabels dependencyLabel)
  64. {
  65.     if (gDependenciesByNotifier)
  66.         gDependenciesByNotifier->RemoveDependency(notifier, dependent, dependencyLabel);
  67.     if (gDependenciesByDependent)
  68.         gDependenciesByDependent->RemoveDependency(notifier, dependent, dependencyLabel);
  69. }
  70.  
  71. //--------------------------------------------------------------------------------------------------
  72. #pragma segment DepRes
  73.  
  74. //RCR Former nested routines
  75. pascal void DeleteByDependent(ArrayIndex index,
  76.                               TObject* notifier,
  77.                               TObject* dependent,
  78.                               DependencyLabels dependencyLabel,
  79.                               void*                /* staticLink */)
  80.  
  81. {
  82.     gDependenciesByDependent->DeleteElementsAt(index, 1);
  83.     gDependenciesByNotifier->RemoveDependency(notifier, dependent, dependencyLabel);
  84. }
  85.  
  86.  
  87. pascal void DeleteByNotifier(ArrayIndex index,
  88.                              TObject* notifier,
  89.                              TObject* dependent,
  90.                              DependencyLabels dependencyLabel,
  91.                              void*                /* staticLink */)
  92.  
  93. {
  94.     gDependenciesByNotifier->DeleteElementsAt(index, 1);
  95.     gDependenciesByDependent->RemoveDependency(notifier, dependent, dependencyLabel);
  96. }
  97.  
  98.  
  99. pascal void RemoveDependencies(TObject* anObject)
  100. {
  101.     long NullStaticLink;                        // Use &NullStaticLink 
  102.  
  103.     if (gDependenciesByDependent)
  104.         gDependenciesByDependent->EachDependencyWithDependent(anObject, DeleteByDependent, &NullStaticLink);
  105.     if (gDependenciesByNotifier)
  106.         gDependenciesByNotifier->EachDependencyWithNotifier(anObject, DeleteByNotifier, &NullStaticLink);
  107. }
  108.  
  109. //--------------------------------------------------------------------------------------------------
  110. #pragma segment DepRes
  111.  
  112. pascal void EachDependentOf(TObject* notifier,
  113.                             DoToObjectType DoToDependent,
  114.                             void* staticLink)
  115. {
  116.     if (gDependenciesByNotifier)
  117.         gDependenciesByNotifier->EachDependentDo(notifier, DoToDependent, staticLink);
  118. }
  119.  
  120. //--------------------------------------------------------------------------------------------------
  121. #pragma segment DepRes
  122.  
  123. pascal void EachNotifierOf(TObject* dependent,
  124.                            DoToObjectType DoToNotifier,
  125.                            void* staticLink)
  126. {
  127.     if (gDependenciesByDependent)
  128.         gDependenciesByDependent->EachNotifierDo(dependent, DoToNotifier, staticLink);
  129. }
  130.  
  131. //--------------------------------------------------------------------------------------------------
  132. #pragma segment DepRes
  133. pascal void MarkObject(TObject* anObject, Boolean state)
  134. {
  135.     ArrayIndex index;
  136.     DependencyPtr p;
  137.  
  138.     if (anObject)
  139.     {
  140.         if ((gDependenciesByDependent) && gDependenciesByDependent->FindDependent(anObject, index))
  141.         {
  142.             p = (DependencyPtr)gDependenciesByDependent->ComputeAddress(index);
  143.             if ((state) != (p->dependencyLabel < 0))
  144.                 p->dependencyLabel = -(p->dependencyLabel);
  145.         }
  146.         else if ((gDependenciesByNotifier) && gDependenciesByNotifier->FindNotifier(anObject, index))
  147.         {
  148.             p = (DependencyPtr)gDependenciesByNotifier->ComputeAddress(index);
  149.             if ((state) != (p->dependencyLabel < 0))
  150.                 p->dependencyLabel = -(p->dependencyLabel);
  151.         }
  152.     }
  153. }
  154.  
  155. //--------------------------------------------------------------------------------------------------
  156. #pragma segment DepRes
  157. pascal Boolean IsObjectMarked(TObject* anObject)
  158. {
  159.     ArrayIndex index;
  160.  
  161.     if (anObject)
  162.     {
  163.         if ((gDependenciesByDependent) && gDependenciesByDependent->FindDependent(anObject, index))
  164.         {
  165.             return (((DependencyPtr)gDependenciesByDependent->ComputeAddress(index))->dependencyLabel < 0);
  166.         }
  167.         else if ((gDependenciesByNotifier) && gDependenciesByNotifier->FindNotifier(anObject, index))
  168.         {
  169.             return (((DependencyPtr)gDependenciesByNotifier->ComputeAddress(index))->dependencyLabel < 0);
  170.         }
  171.         else
  172.             return FALSE;
  173.     }
  174.     else
  175.         return FALSE;
  176. }
  177.  
  178. //--------------------------------------------------------------------------------------------------
  179. //    CDependencyComparer
  180. //--------------------------------------------------------------------------------------------------
  181.  
  182. #pragma segment DepRes
  183.  
  184. class CDependencyComparer
  185. {
  186.     Dependency&     fTargetDependency;
  187.     TDependencies*  fDependencies;
  188. public:
  189.     // Constructor
  190.     CDependencyComparer(Dependency& targetDependency,
  191.                      TDependencies* theDependencies) :
  192.         fTargetDependency(targetDependency),
  193.         fDependencies(theDependencies) {}
  194.  
  195.     pascal CompareResult CompareDependency(ArrayIndex index);
  196. };
  197.  
  198. #pragma segment DepRes
  199.  
  200. pascal CompareResult CDependencyComparer::CompareDependency(ArrayIndex index)
  201. {
  202.     return fDependencies->CompareElements(&fTargetDependency, fDependencies->ComputeAddress(index));
  203. }
  204.  
  205. //--------------------------------------------------------------------------------------------------
  206. //    CObjectIterator
  207. //--------------------------------------------------------------------------------------------------
  208.  
  209. //--------------------------------------------------------------------------------------------------
  210. #pragma segment DepRes
  211.  
  212. class CDependentIterator
  213. {
  214.     DoToObjectType& fDoToObject;
  215.     void*& fStaticLink;
  216. public:
  217.     // Constructor
  218.     CDependentIterator(DoToObjectType& DoToObject,
  219.                   void*& staticLink) :
  220.         fDoToObject(DoToObject),
  221.         fStaticLink(staticLink)
  222.     {
  223.     }
  224.  
  225.     pascal void DoToDependent(ArrayIndex            /* index */,
  226.                              TObject*            /* notifier */,
  227.                              TObject* dependent,
  228.                              DependencyLabels    /* dependencyLabel */);
  229.     pascal void DoToNotifier(ArrayIndex            /* index */,
  230.                              TObject*            /* notifier */,
  231.                              TObject* dependent,
  232.                              DependencyLabels    /* dependencyLabel */);
  233.  
  234. };
  235.  
  236. #pragma segment DepRes
  237.  
  238. pascal void CDependentIterator::DoToDependent(ArrayIndex    /* index */,
  239.                                         TObject*        /* notifier */ ,
  240.                                         TObject*         dependent,
  241.                                         DependencyLabels/* dependencyLabel */)
  242.  
  243. {
  244.     fDoToObject(dependent, fStaticLink);
  245. }
  246.  
  247. #pragma segment DepRes
  248.  
  249. pascal void CDependentIterator::DoToNotifier(ArrayIndex    /* index */,
  250.                                         TObject*        notifier,
  251.                                         TObject*         /* dependent */,
  252.                                         DependencyLabels/* dependencyLabel */)
  253.  
  254. {
  255.     fDoToObject(notifier, fStaticLink);
  256. }
  257.  
  258. //--------------------------------------------------------------------------------------------------
  259. //    TDependencies
  260. //--------------------------------------------------------------------------------------------------
  261.  
  262. //--------------------------------------------------------------------------------------------------
  263. #pragma segment DepRes
  264.  
  265. pascal void TDependencies::IDependencies(void)
  266. {
  267.     this->IDynamicArray(1, sizeof(Dependency));
  268. }
  269.  
  270. //--------------------------------------------------------------------------------------------------
  271. #pragma segment DepRes
  272.  
  273. pascal void TDependencies::AddDependency(TObject* notifier,
  274.                                          TObject* dependent,
  275.                                          DependencyLabels dependencyLabel)
  276. {
  277.     ArrayIndex index;
  278.  
  279.     if (!FindDependency(notifier, dependent, dependencyLabel, index))
  280.         this->InsertDependencyBefore(index, notifier, dependent, dependencyLabel);
  281. }
  282.  
  283. //--------------------------------------------------------------------------------------------------
  284. #pragma segment DepRes
  285.  
  286. pascal void TDependencies::InsertDependencyBefore(ArrayIndex index,
  287.                                                   TObject* notifier,
  288.                                                   TObject* dependent,
  289.                                                   DependencyLabels dependencyLabel)
  290. {
  291.     Dependency newDependency(notifier,dependent,dependencyLabel);
  292.  
  293.     this->InsertElementsBefore(index, &newDependency, 1);
  294. }
  295.  
  296.  
  297. #pragma segment DepRes
  298.  
  299. pascal Boolean TDependencies::FindDependency(TObject* notifier,
  300.                                              TObject* dependent,
  301.                                              DependencyLabels dependencyLabel,
  302.                                              ArrayIndex& index)
  303.  
  304.  
  305. {
  306.     Dependency targetDependency(notifier,dependent,dependencyLabel);
  307.     CDependencyComparer aDependencyComparer(targetDependency, this);
  308.  
  309.     return this->DoSearchElement((CompareIndexType) & CDependencyComparer::CompareDependency, &aDependencyComparer, index);
  310. }
  311.  
  312. //--------------------------------------------------------------------------------------------------
  313. #pragma segment DepRes
  314.  
  315. pascal void TDependencies::RemoveDependency(TObject* notifier,
  316.                                             TObject* dependent,
  317.                                             DependencyLabels dependencyLabel)
  318. {
  319.     ArrayIndex index;
  320.  
  321.     if (this->FindDependency(notifier, dependent, dependencyLabel, index))
  322.         this->DeleteElementsAt(index, 1);
  323. }
  324.  
  325. //--------------------------------------------------------------------------------------------------
  326. #pragma segment MAFields
  327.  
  328. pascal void TDependencies::Fields(TObject* obj)    // override 
  329. {
  330.     obj->DoToField("TDependencies", (Ptr)NULL, bClass);
  331.  
  332.     inherited::Fields(obj);
  333. }
  334.  
  335.  
  336. #pragma segment MAFields
  337.  
  338. pascal void TDependencies::DynamicFields(TObject* obj)// override 
  339. {
  340.     CArrayIterator iter(this);
  341.     Str255 aString;
  342.  
  343.     obj->DoToField("Dynamic Fields", NULL, bTitle);
  344.  
  345.     for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
  346.     {
  347.         Dependency& theDependency = *((DependencyPtr) this->ComputeAddress(i));
  348.  
  349.         NumToString(i, aString);
  350.         aString = ".At[" + aString + "]";
  351.         obj->DoToField(aString, &theDependency.notifier, bTitle);
  352.         obj->DoToField("Notifier", &theDependency.notifier, bObject);
  353.         obj->DoToField("Dependent", &theDependency.dependent, bObject);
  354.         obj->DoToField("dependencyLabel", &theDependency.dependencyLabel, bInteger);
  355.     }
  356. }
  357.  
  358. //--------------------------------------------------------------------------------------------------
  359. // TDependenciesByNotifier 
  360. //--------------------------------------------------------------------------------------------------
  361. #pragma segment DepRes
  362.  
  363. pascal CompareResult TDependenciesByNotifier::CompareElements(void* Element1,
  364.                                                               void* Element2)// override 
  365.  
  366. {
  367.     Dependency & Dependency1 = *((DependencyPtr)Element1);
  368.     Dependency & Dependency2 = *((DependencyPtr)Element2);
  369.  
  370.     if (Dependency1.notifier > Dependency2.notifier)
  371.         return kItem1GreaterThanItem2;
  372.     else if (Dependency1.notifier < Dependency2.notifier)
  373.         return kItem1LessThanItem2;
  374.     else
  375.     {
  376.         if ((Dependency1.dependent == NULL) || (Dependency2.dependent == NULL) || (Dependency1.dependent == Dependency2.dependent))
  377.             return kItem1EqualItem2;
  378.         else if (Dependency1.dependent < Dependency2.dependent)
  379.             return kItem1LessThanItem2;
  380.         else
  381.             return kItem1GreaterThanItem2;
  382.     }
  383. }
  384.  
  385. //--------------------------------------------------------------------------------------------------
  386. #pragma segment DepRes
  387.  
  388. pascal Boolean TDependenciesByNotifier::FindNotifier(TObject* notifier,
  389.                                                      ArrayIndex& index)
  390. {
  391.     Dependency targetDependency(notifier,NULL,kNoLabel);
  392.     CDependencyComparer aDependencyComparer(targetDependency, this);
  393.  
  394.     return this->DoSearchElement((CompareIndexType) & CDependencyComparer::CompareDependency, &aDependencyComparer, index);
  395. }
  396.  
  397. #pragma segment DepRes
  398.  
  399. pascal void TDependenciesByNotifier::EachDependencyWithNotifier(TObject* notifier,
  400.                                                                 DoToDependencyType DoToDependency,
  401.                                                                 void* staticLink)
  402.  
  403.  
  404. {
  405.     ArrayIndex foundIndex;
  406.  
  407.     // Although the lists are ordered the search is a binary search and can return
  408.     // a random entry from the set of matching entries.  First back up the the _real_
  409.     // first matching entry and then we will march forward applying the DoToDependency
  410.  
  411.     if (this->FindNotifier(notifier, foundIndex))
  412.     {
  413.         {// extra block to ensure iterators are destroyed in fifo order
  414.             CArrayIterator iter(this, 1, foundIndex, kIterateBackward);
  415.             for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
  416.             {            
  417.                 if (((DependencyPtr)this->ComputeAddress(i))->notifier == notifier)
  418.                     foundIndex = i;
  419.                 else
  420.                     break;
  421.             }
  422.         }
  423.     
  424.         {// extra block to ensure iterators are destroyed in fifo order
  425.             CArrayIterator iter(this, foundIndex, fSize, kIterateForward);
  426.             for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
  427.             {
  428.                 Dependency & theDependency = *((DependencyPtr)this->ComputeAddress(i));
  429.             
  430.                 if (theDependency.notifier == notifier)
  431.                     DoToDependency(i, theDependency.notifier, theDependency.dependent, theDependency.dependencyLabel, staticLink);
  432.                 else
  433.                     break;
  434.             }
  435.         }
  436.     }
  437. }
  438.  
  439. //--------------------------------------------------------------------------------------------------
  440. #pragma segment DepRes
  441.  
  442. pascal void TDependenciesByNotifier::EachDependentDo(TObject* notifier,
  443.                                                      DoToObjectType DoToDependent,
  444.                                                      void* staticLink)
  445.  
  446.  
  447. {
  448.     CDependentIterator aDependentIterator(DoToDependent, staticLink);
  449.  
  450.     this->EachDependencyWithNotifier(notifier, (DoToDependencyType) &CDependentIterator::DoToDependent, &aDependentIterator);
  451. }
  452.  
  453. //--------------------------------------------------------------------------------------------------
  454. // TDependenciesByDependent 
  455. //--------------------------------------------------------------------------------------------------
  456.  
  457. //--------------------------------------------------------------------------------------------------
  458. #pragma segment DepRes
  459.  
  460. pascal CompareResult TDependenciesByDependent::CompareElements(void* Element1,
  461.                                                                void* Element2)    // override 
  462. {
  463.     Dependency& Dependency1 = *((DependencyPtr)Element1);
  464.     Dependency& Dependency2 = *((DependencyPtr)Element2);
  465.  
  466.     if (Dependency1.dependent > Dependency2.dependent)
  467.         return kItem1GreaterThanItem2;
  468.     else if (Dependency1.dependent < Dependency2.dependent)
  469.         return kItem1LessThanItem2;
  470.     else
  471.     {
  472.         if ((Dependency1.notifier == NULL) || (Dependency2.notifier == NULL) || (Dependency1.notifier == Dependency2.notifier))
  473.             return kItem1EqualItem2;
  474.         else if (Dependency1.notifier < Dependency2.notifier)
  475.             return kItem1LessThanItem2;
  476.         else
  477.             return kItem1GreaterThanItem2;
  478.     }
  479. }
  480.  
  481. //--------------------------------------------------------------------------------------------------
  482. #pragma segment DepRes
  483.  
  484. pascal Boolean TDependenciesByDependent::FindDependent(TObject* dependent,
  485.                                                        ArrayIndex& index)
  486. {
  487.     Dependency targetDependency(NULL,dependent,kNoLabel);
  488.     CDependencyComparer aDependencyComparer(targetDependency, this);
  489.  
  490.     return this->DoSearchElement((CompareIndexType) &CDependencyComparer::CompareDependency, &aDependencyComparer, index);
  491. }
  492.  
  493. //--------------------------------------------------------------------------------------------------
  494. #pragma segment DepRes
  495.  
  496. pascal void TDependenciesByDependent::EachNotifierDo(TObject* dependent,
  497.                                                      DoToObjectType DoToNotifier,
  498.                                                      void* staticLink)
  499.  
  500.  
  501. {
  502.     CDependentIterator aDependentIterator(DoToNotifier, staticLink);
  503.  
  504.     this->EachDependencyWithDependent(dependent, (DoToDependencyType) &CDependentIterator::DoToNotifier, &aDependentIterator);
  505. }
  506.  
  507. //--------------------------------------------------------------------------------------------------
  508. #pragma segment DepRes
  509.  
  510. pascal void TDependenciesByDependent::EachDependencyWithDependent(TObject* dependent,
  511.                                                                   DoToDependencyType DoToDependency,
  512.                                                                   void* staticLink)
  513. {
  514.     ArrayIndex foundIndex;
  515.  
  516.     // Although the lists are ordered the search is a binary search and can return
  517.     // a random entry from the set of matching entries.  First back up the the _real_
  518.     // first matching entry and then we will march forward applying the DoToDependency
  519.  
  520.     if (this->FindDependent(dependent, foundIndex))
  521.     {
  522.         {// extra block to ensure iterators are destroyed in fifo order
  523.             CArrayIterator iter(this, 1, foundIndex, kIterateBackward);
  524.             for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
  525.             {            
  526.                 if (((DependencyPtr)this->ComputeAddress(i))->dependent == dependent)
  527.                     foundIndex = i;
  528.                 else
  529.                     break;
  530.             }
  531.         }
  532.     
  533.         {// extra block to ensure iterators are destroyed in fifo order
  534.             CArrayIterator iter(this, foundIndex, fSize, kIterateForward);
  535.             for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
  536.             {
  537.                 Dependency & theDependency = *((DependencyPtr)this->ComputeAddress(i));
  538.             
  539.                 if (theDependency.dependent == dependent)
  540.                     DoToDependency(i, theDependency.notifier, theDependency.dependent, theDependency.dependencyLabel, staticLink);
  541.                 else
  542.                     break;
  543.             }
  544.         }
  545.     }
  546. }
  547.  
  548.  
  549.